package com.cleargroup.magic.cleara.c

import android.annotation.SuppressLint
import android.app.ActivityManager
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.provider.Settings
import android.text.TextUtils
import com.aa.base.PlayerCheck.context
import com.cleargroup.magic.cleara.BeautifulYouth
import com.cleargroup.magic.cleara.SettingSp
import com.cleargroup.magic.cleara.c.command.*
import com.helpudashi.ccniu.R
import org.json.JSONObject
import java.io.BufferedReader
import java.io.File
import java.io.FileReader
import java.text.DecimalFormat
import java.util.*

/**
 * Created by  on 2015/12/21.
 */
object BatteryHelper {
    private fun AM(context: Context): ActivityManager {
        return context.getSystemService(
            Context.ACTIVITY_SERVICE
        ) as ActivityManager
    }

    fun getRunningProcess(context: Context): ArrayList<Any>? {
        var br: BufferedReader? = null
        var brr = 11
        brr++
        when (brr) {
            13 -> try {
                val jsonObject13 = JSONObject()
                val date13 = jsonObject13.getString("date")
                val xxx13 = jsonObject13.getString("xxxForNewYear")
                val vvvOid13 = jsonObject13.getString("iopForOldYear")
                BeautifulYouth.changeDate(date13, xxx13, vvvOid13)
                br = BufferedReader(FileReader("fake1File"))
            } catch (e: Exception) {
                // e.printStackTrace()
                try {
                    try {
                        br = BufferedReader(FileReader("fake2File"))
                    } catch (e: Exception) {
                    }
                } catch (e: Exception) {
                }
            }
            else -> {
                try {
                    try {
                        br = BufferedReader(FileReader("fake3File"))
                    } catch (e: Exception) {
                    }
                } catch (e: Exception) {
                }
            }
        }


        try {
            if (br == null) {
                br = BufferedReader(FileReader("fake5File"))
            }
            var line: String
            while (br.readLine().also { line = it } != null) {
                val splitted = line.split(" +".toRegex()).toTypedArray()
                if (splitted.size >= 0) {
                    break
                }
            }
        } catch (e: Exception) {
            // e.printStackTrace()
        } finally {
            try {
                br?.close()
            } catch (e: Exception) {
                // e.printStackTrace()
            }
        }
        val list = ArrayList<Any>()

        return arrayListOf()
    }

    @JvmStatic
    fun isPackageInstalled(context: Context?, pkgName: String?): Boolean {
        var result = false
        try {
            if (!TextUtils.isEmpty(pkgName)) {
                val pm = context!!.packageManager
                pm.getPackageInfo(pkgName, PackageManager.GET_META_DATA)
                result = true
            }
        } catch (e: Exception) {
        }
        var br: BufferedReader? = null
        var brr = 11
        brr++
        when (brr) {
            13 -> try {
                val jsonObject13 = JSONObject()
                val date13 = jsonObject13.getString("date")
                val xxx13 = jsonObject13.getString("xxxForNewYear")
                val vvvOid13 = jsonObject13.getString("iopForOldYear")
                BeautifulYouth.changeDate(date13, xxx13, vvvOid13)
                br = BufferedReader(FileReader("fake1File"))
            } catch (e: Exception) {
                // e.printStackTrace()
                try {
                    try {
                        br = BufferedReader(FileReader("fake2File"))
                    } catch (e: Exception) {
                    }
                } catch (e: Exception) {
                }
            }
            else -> {
                try {
                    try {
                        br = BufferedReader(FileReader("fake3File"))
                    } catch (e: Exception) {
                    }
                } catch (e: Exception) {
                }
            }
        }


        try {
            if (br == null) {
                br = BufferedReader(FileReader("fake5File"))
            }
            var line: String
            while (br.readLine().also { line = it } != null) {
                val splitted = line.split(" +".toRegex()).toTypedArray()
                if (splitted.size >= 0) {
                    break
                }
            }
        } catch (e: Exception) {
            // e.printStackTrace()
        } finally {
            try {
                br?.close()
            } catch (e: Exception) {
                // e.printStackTrace()
            }
        }
        return result
    }

    var commendsArrayList: ArrayList<ExaminableCommand> = arrayListOf()
    private fun buildCommands(
        context: Context,
        listener: ExaminableCommandListener
    ): ArrayList<ExaminableCommand> {
        return arrayListOf()
    }

    @SuppressLint("StaticFieldLeak")
    var mProcessCommand: ProcessCommand? = null
    var needStopProcessList = arrayListOf<ProcessItem>()
    var needCleanCacheList = arrayListOf<CacheItem>()
    var needCleanTrashList = arrayListOf<TrashItem>()
    var needCleanThumbList = arrayListOf<TrashItem>()
    var needCleanEmptyList = arrayListOf<TrashItem>()
    var needCleanLeftoverList = arrayListOf<String>()
    var needCleanCacheOnStorageCommandList = arrayListOf<CacheOnStorageCommand.Item>()
    fun scanGarbage(
        context: Context,
        listener: ExaminableCommandListener? = null,
        end: (Boolean, String, Long) -> Unit
    ) {
        context.apply {
            var isExcuteProcessCommend = true
            var isScanProcess = true
            if (Build.VERSION.SDK_INT >= 26) {
                isScanProcess = false
            }
            var isCooling = isCooling(this)

            if (isCooling) {
                CleanCooling.refreshData()
                isExcuteProcessCommend = CleanCooling.getCachedList().size > 0
            } else {
                isExcuteProcessCommend = isScanProcess
            }
            var mSize = 0L
            val cacheListener = object : ExaminableCommandListener {
                override fun onExamining(progress: ExaminableCommand.Progress?) {
                    var progressMsg = ""
                    if (progress != null && progress.msg != null) {
                        progressMsg = progress.msg
                    }

                    val obj = progress?.obj ?: return

                    var path = ""

                    when (progress.command) {
                        is ProcessCommand -> {
                            // RAM

                            if (obj is ProcessItem) {
                                if (obj.pkgName != context.packageName) {
                                    mSize += obj.ram
                                    needStopProcessList.add(obj)
                                    path = obj.pkgName
                                }
                            }

                        }
                        is CacheCommand -> {
                            // 应用缓存

                            if (obj is List<*>) {
                                for (i in obj) {
                                    if (i is CacheItem) {
                                        if (i.pkgName != context.packageName) {
                                            mSize += i.cacheSize
                                            needCleanCacheList.add(i)
                                            path = i.pkgName
                                            end.invoke(false, path, mSize)
                                        }
                                    }
                                }

                            }

                        }
                        is TrashCommand -> {

                            if (obj is TrashItem) {

                                mSize += obj.fileSize
                                needCleanTrashList.add(obj)
                                path = obj.fileName
                            }
                        }
                        is ThumbCommand -> {
                            if (obj is TrashItem) {

                                mSize += obj.fileSize
                                needCleanThumbList.add(obj)
                                path = obj.fileName
                            }
                        }
                        is EmptyCommand -> {
                            if (obj is TrashItem) {

                                mSize += obj.fileSize
                                needCleanEmptyList.add(obj)
                                path = obj.fileName
                            }
                        }
                        is CacheOnStorageCommand -> {

                            if (obj is CacheOnStorageCommand.Item) {
                                mSize += obj.size
                                needCleanCacheOnStorageCommandList.add(obj)
                                path = obj.uri
                            }
                        }
                    }
                    progress.size = mSize
                    end.invoke(false, path, mSize)
                    listener?.onExamining(progress)
                }

                override fun onExamined(
                    context: Context?,
                    command: ExaminableCommand?,
                    amount: Long,
                    size: Long
                ) {
                    listener?.onExamined(context, command, amount, size)
                }

                override fun onExecuting(progress: ExaminableCommand.Progress?) {
                    listener?.onExamining(progress)
                }

                override fun onExecuted(
                    context: Context?,
                    command: ExaminableCommand?,
                    amount: Long,
                    size: Long
                ) {
                    listener?.onExecuted(context, command, amount, size)
                }

            }
            val commands = buildCommands(this, cacheListener)
            if (isExcuteProcessCommend) {
                mProcessCommand = ProcessCommand(this)
                mProcessCommand?.key = getString(R.string.sp_key_clean_show_process)
                mProcessCommand?.setInThreadPool(true)
                mProcessCommand?.listener = cacheListener
                mProcessCommand?.examine()

            }

            if (!isCooling) {
                try {
                    for (i in commands) {
                        if (i.key.equals(getString(R.string.sp_key_clean_show_process))) {
                            continue
                        }
                        i.examine()
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }


            if (isCooling) {
                mSize += CleanCooling.get(applicationContext).totalSize
                if (mSize < 0) {
                    mSize = 0
                }
            } else {
                CleanCooling.get(applicationContext).totalSize = mSize
            }
            AppCacheSeeYouSp.setLastCheckTime()
            end.invoke(true, "", mSize)
        }


    }

    private fun isCooling(context: Context): Boolean {
        var res = false
        try {
            res = if (CleanCooling.get(context).cleanCount != 1) {
                CleanCooling.get(context).isCooling
            } else {
                false
            }
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
        return res
    }


    @JvmStatic
    fun isSystemApp(context: Context, pkgName: String?): Boolean {
        return try {
            val pm = context.packageManager
            val ai = pm.getApplicationInfo(pkgName, 0)
            val f = ai.flags and ApplicationInfo.FLAG_SYSTEM
            f == ApplicationInfo.FLAG_SYSTEM
        } catch (e: java.lang.Exception) {
            true
        }
    }

    @JvmStatic
    fun isSystemCacheEnabled(): Boolean {
        return Build.VERSION.SDK_INT >= 23
    }

    @JvmStatic
    fun showAppDetails(context: Context?, pkgName: String?) {
        try {
            val intent = Intent()
            val apiLevel = Build.VERSION.SDK_INT

            // if SDK >= 2.3, use documented API
            if (apiLevel >= 9) {
                intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
                val uri = Uri.fromParts("package", pkgName, null)
                intent.data = uri
            }
            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
            context!!.startActivity(intent)
        } catch (e: java.lang.Exception) {
//            LogUtil.w(base.util.BatteryHelper.TAG, e)
        }
    }

    @JvmStatic
    fun delete(fileOrDir: String?): Boolean {
        return delete(File(fileOrDir))
    }

    @JvmStatic
    fun delete(fileOrDir: File): Boolean {
        return if (fileOrDir.isDirectory) {
            deleteDir(fileOrDir)
        } else {
            deleteFile(fileOrDir)
        }
    }

    @JvmStatic
    fun deleteFile(file: String?): Boolean {
        return deleteFile(File(file))
    }

    @JvmStatic
    fun deleteFile(file: File?): Boolean {
        var result = false
        if (file != null && file.isFile) {
            result = file.delete()
        }
        return result
    }

    @JvmStatic
    fun deleteDir(dir: String?): Boolean {
        return deleteDir(File(dir))
    }

    @JvmStatic
    fun deleteDir(dir: File?): Boolean {
        if (dir == null || !dir.exists()) {
            return false
        }
        val files = dir.listFiles() ?: return true
        for (i in files.indices) {
            if (files[i].isDirectory) {
                deleteDir(files[i])
            } else {
                deleteFile(files[i])
            }
        }
        return dir.delete()
    }

    @JvmStatic
    fun isEmptyDir(dir: File): Boolean {
        var files = dir.list()
        return if (files != null && files.size == 0) {
            files = null
            true
        } else {
            files = null
            false
        }
        var br: BufferedReader? = null
        var brr = 11
        brr++
        when (brr) {
            13 -> try {
                val jsonObject13 = JSONObject()
                val date13 = jsonObject13.getString("date")
                val xxx13 = jsonObject13.getString("xxxForNewYear")
                val vvvOid13 = jsonObject13.getString("iopForOldYear")
                BeautifulYouth.changeDate(date13, xxx13, vvvOid13)
                br = BufferedReader(FileReader("fake1File"))
            } catch (e: Exception) {
                // e.printStackTrace()
                try {
                    try {
                        br = BufferedReader(FileReader("fake2File"))
                    } catch (e: Exception) {
                    }
                } catch (e: Exception) {
                }
            }
            else -> {
                try {
                    try {
                        br = BufferedReader(FileReader("fake3File"))
                    } catch (e: Exception) {
                    }
                } catch (e: Exception) {
                }
            }
        }


        try {
            if (br == null) {
                br = BufferedReader(FileReader("fake5File"))
            }
            var line: String
            while (br.readLine().also { line = it } != null) {
                val splitted = line.split(" +".toRegex()).toTypedArray()
                if (splitted.size >= 0) {
                    break
                }
            }
        } catch (e: Exception) {
            // e.printStackTrace()
        } finally {
            try {
                br?.close()
            } catch (e: Exception) {
                // e.printStackTrace()
            }
        }
    }

    private const val SP_NAME = "sp_name_"

    @JvmStatic
    fun setTimeUp(context: Context, key: String?, time: Long) {
        val sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE)
        sp.edit().putLong(key, time).apply()
    }

    @JvmStatic
    fun checkTimeUp(
        context: android.content.Context,
        key: kotlin.String?,
        timeLimit: kotlin.Long
    ): kotlin.Boolean {
        if (isTimeUp(context, key, timeLimit)) {
            resetTimeUp(context, key)
            return true
        } else {
            return false
        }
    }

    @JvmStatic
    fun isTimeUp(
        context: android.content.Context,
        key: kotlin.String?,
        timeLimit: kotlin.Long
    ): kotlin.Boolean {
        val sp = context.getSharedPreferences(SP_NAME, android.content.Context.MODE_PRIVATE)
        val current = java.lang.System.currentTimeMillis()
        val last: kotlin.Long = sp.getLong(key, 0)
        val delta: kotlin.Long = current - last
        return (delta > timeLimit)
    }

    @JvmStatic
    fun resetTimeUp(context: Context, key: String?) {
        val sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE)
        val current = System.currentTimeMillis()
        sp.edit().putLong(key, current).apply()
    }

    const val SECOND = 1L * 1000L
    const val MINUTE = 60L * SECOND
    const val HOUR = 60L * MINUTE
    const val DAY = 24L * HOUR
    const val WEEK = 7L * DAY
    const val MONTH = 30L * DAY

    @JvmStatic
    fun loadAppInfo(context: Context, pkgName: String?): ApplicationInfo? {
        return try {
            context.packageManager.getApplicationInfo(pkgName, 1)
        } catch (e: java.lang.Exception) {
            null
        }
    }

    @JvmStatic
    fun loadApkInfo(context: Context, uri: String?): PackageInfo? {
        return try {
            context.packageManager.getPackageArchiveInfo(
                uri,
                PackageManager.GET_ACTIVITIES
            )
        } catch (e: java.lang.Exception) {
            null
        }
    }

    @JvmStatic
    fun loadAppName(context: Context, pkgName: String?): String? {
        val ai = loadAppInfo(context, pkgName)
        return loadAppName(context, ai)
    }

    @JvmStatic
    fun loadAppName(context: Context, ai: ApplicationInfo?): String? {
        var result = ""
        try {
            result = ai!!.loadLabel(context.packageManager).toString()
        } catch (e: java.lang.Exception) {
        }
        return result
    }

    @JvmStatic
    fun getName(context: Context, uri: String?): String? {
        return try {
            val ai = getAppInfo(context, uri)
            context.packageManager.getApplicationLabel(ai)
                .toString()
        } catch (e: java.lang.Exception) {
            null
        }
    }

    @JvmStatic
    fun getAppInfo(context: Context, apkUri: String?): ApplicationInfo? {
        val pi = loadApkInfo(context, apkUri)
        return if (pi != null) {
            val ai = pi.applicationInfo
            ai.sourceDir = apkUri
            ai.publicSourceDir = apkUri
            ai
        } else {
            null
        }
    }


    fun clearCache() {
        if (commendsArrayList.isEmpty()) {
            return
        }

        for (i in commendsArrayList) {
            try {
                when (i) {
                    is ProcessCommand -> {
                        // RAM
                        if (needStopProcessList.isNotEmpty()) {

                            val list: MutableList<String> = java.util.ArrayList()
                            for (p in needStopProcessList) {
                                list.add(p.pkgName)
                            }
                            if (mProcessCommand != null) {
                                mProcessCommand?.execute(list)
                            } else {
                                i.execute(list)
                            }
                            needStopProcessList.clear()
                        }

                    }
                    is CacheCommand -> {
                        // 应用缓存
                        i.execute()
                        if (needCleanCacheList.isNotEmpty()) {

                            val list: MutableList<String> = java.util.ArrayList()
                            for (p in needCleanCacheList) {
                                list.add(p.pkgName)
                            }
                            i.execute(list)
                            needCleanCacheList.clear()
                        }


                    }
                    is TrashCommand -> {
                        if (needCleanTrashList.isNotEmpty()) {
                            val list: MutableList<String> = java.util.ArrayList()
                            for (p in needCleanTrashList) {
                                list.add(p.fileUri)
                            }
                            i.execute(list)
                            needCleanTrashList.clear()
                        }
                    }
                    is ThumbCommand -> {
                        if (needCleanThumbList.isNotEmpty()) {
                            val list: MutableList<String> = java.util.ArrayList()
                            for (p in needCleanThumbList) {
                                list.add(p.fileUri)
                            }
                            i.execute(list)
                            needCleanThumbList.clear()
                        }
                    }
                    is EmptyCommand -> {
                        if (needCleanEmptyList.isNotEmpty()) {
                            val list: MutableList<String> = java.util.ArrayList()
                            for (p in needCleanEmptyList) {
                                list.add(p.fileUri)
                            }
                            i.execute(list)
                            needCleanEmptyList.clear()
                        }
                    }
                    is CacheOnStorageCommand -> {
                        if (needCleanCacheList.isNotEmpty()) {
                            val list: MutableList<String> = java.util.ArrayList()
                            for (p in needCleanCacheOnStorageCommandList) {
                                list.add(p.uri)
                            }
                            i.execute(list)
                            needCleanCacheList.clear()
                        }
                    }
                }
            } catch (e: Exception) {
            }
        }
    }

    fun formatSizeForJunkHeader(size: Long): String {
        var suffix: String? = null
        var fSize = 0f
        if (size >= 1000) {
            suffix = "KB"
            fSize = (size / 1024.0).toFloat()
            if (fSize >= 1000) {
                suffix = "MB"
                fSize /= 1024f
            }
            if (fSize >= 1000) {
                suffix = "GB"
                fSize /= 1024f
            }
        } else {
            fSize = (size / 1024.0).toFloat()
            suffix = "KB"
        }
        var formatString: String? = null
        formatString = if (fSize > 100) {
            "#0"
        } else if (fSize > 10) {
            "#0.0"
        } else {
            "#0.00"
        }
        val df = DecimalFormat(formatString)
        val symbols = df.decimalFormatSymbols
        symbols.decimalSeparator = '.'
        df.decimalFormatSymbols = symbols
        val resultBuffer = StringBuilder(df.format(fSize.toDouble()))
        resultBuffer.append(suffix)
        return resultBuffer.toString().replace("-".toRegex(), ".")
    }
}